package com.pureut.order.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pureut.common.core.exception.GlobalException;
import com.pureut.common.core.web.domain.AjaxResult;
import com.pureut.common.datascope.annotation.DataScope;
import com.pureut.common.security.utils.DictUtils;
import com.pureut.common.security.utils.SecurityUtils;
import com.pureut.order.domain.ProcurementPlan;
import com.pureut.order.domain.ProcurementPlanBack;
import com.pureut.order.domain.ProcurementPlanDetail;
import com.pureut.order.dto.ProcurementPlanDto;
import com.pureut.order.mapper.ProcurementPlanBackMapper;
import com.pureut.order.mapper.ProcurementPlanDetailMapper;
import com.pureut.order.mapper.ProcurementPlanMapper;
import com.pureut.order.service.ProcurementPlanBackService;
import com.pureut.order.service.ProcurementPlanDetailService;
import com.pureut.order.service.ProcurementPlanService;
import com.pureut.order.vo.*;
import com.pureut.system.api.FeignService;
import com.pureut.system.api.domain.SysDept;
import com.pureut.system.api.domain.SysDictData;
import com.pureut.system.api.vo.SysAuditHistoryVo;
import com.pureut.system.api.vo.SysWorkbenchAuditAgentVo;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ProcurementPlanServiceImpl extends ServiceImpl<ProcurementPlanMapper, ProcurementPlan> implements ProcurementPlanService {

    @Resource
    ProcurementPlanMapper procurementPlanMapper;

    @Lazy
    @Resource
    ProcurementPlanDetailService procurementPlanDetailService;

    @Resource
    ProcurementPlanDetailMapper procurementPlanDetailMapper;

    @Lazy
    @Resource
    ProcurementPlanBackService procurementPlanBackService;

    @Resource
    ProcurementPlanBackMapper procurementPlanBackMapper;

    @Resource
    FeignService feignService;

    /**
     * 采购计划列表
     *
     * @param procurementPlanVo
     * @return
     */
    @Override
    @DataScope(deptAlias = "a")
    public List<ProcurementPlanDto> getList(ProcurementPlanVo procurementPlanVo) {
        List<ProcurementPlanDto> procurementPlanList = procurementPlanMapper.getprocurementPlanList(procurementPlanVo);
        //获取采购计划状态缓存字典数据
        List<SysDictData> statusArray = DictUtils.getDictCache("procurement_plan_status");
        Map<String, String> actualMap = statusArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //单位
        List<SysDictData> materialUnitArray = DictUtils.getDictCache("sys_material_unit");
        Map<String, String> materialUnit = materialUnitArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取采购计划质量标准
        List<SysDictData> standardArray = DictUtils.getDictCache("quality_standard");
        Map<String, String> standardMap = standardArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        for (ProcurementPlanDto entity : procurementPlanList) {
            //质量标准
            entity.setQualityStandardDict(standardMap.get(entity.getQualityStandard()));
            entity.setStatusDict(actualMap.get(entity.getStatus()));

            //部门
            AjaxResult deptInfo = feignService.getDeptInfo(Long.valueOf(entity.getDemandDept()));
            SysDept accDetailed = JSON.parseObject(JSON.toJSONString(deptInfo.get("data")), SysDept.class);
            entity.setDemandDeptDict(accDetailed.getDeptName());
            entity.setDemandDept(entity.getDemandDept());
            //单位
            entity.setUnitDict(materialUnit.get(entity.getUnit()));
            entity.setUnit(entity.getUnit());
        }
        return procurementPlanList;
    }

    /**
     * 新增采购计划
     *
     * @param procurementPlanVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addProcurementPlan(ProcurementPlanVo procurementPlanVo) throws Exception {

        List<MaterialVo> materialList = procurementPlanVo.getMaterialList();
        List<ProcurementPlan> procurementPlanList = new ArrayList<>();
        for (MaterialVo entity : materialList) {
            ProcurementPlan procurementPlan = new ProcurementPlan();
            String authorityCoding = feignService.getAuthorityCoding("order:purchase:plan:list");
            if (authorityCoding == null) {
                throw new GlobalException("未进行单据配置,单据编码生成失败");
            }
            procurementPlan.setPurchaseNum(authorityCoding)
                    .setDeptId(SecurityUtils.getDeptId())
                    .setStatus(5)
                    .setMaterialId(entity.getMaterialId())
                    .setMaterialCode(entity.getMaterialCode())
                    .setPlanWeight(entity.getPlanWeight())
                    .setMaterialCategory(Integer.parseInt(procurementPlanVo.getMaterialCategory()))
                    .setDemandDept(Long.parseLong(procurementPlanVo.getDemandDept()))
                    .setRemark(procurementPlanVo.getRemark())
                    .setEnclosureUrl(procurementPlanVo.getEnclosureUrl())
//                    .setUnit(Integer.parseInt(entity.getUnit()))
                    .setCreateBy(SecurityUtils.getUsername())
                    .setDemander(SecurityUtils.getUsername())
                    .setCreateTime(new Date())
                    .setQualityStandard(entity.getQualityStandard())
                    .setDemandTime(entity.getDemandTime());
            procurementPlanList.add(procurementPlan);
        }
        try {
            return saveBatch(procurementPlanList);
        } catch (Exception e) {
            throw new SQLException("批量保存失败");
        }
    }

    /**
     * 修改采购计划
     *
     * @param procurementPlanUpdateVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateProcurementPlan(ProcurementPlanUpdateVo procurementPlanUpdateVo) {
        ProcurementPlan procurementPlan = getById(procurementPlanUpdateVo.getId());
        if (2 == procurementPlan.getStatus() || 5 == procurementPlan.getStatus()) {
            procurementPlan.setMaterialCategory(Integer.parseInt(procurementPlanUpdateVo.getMaterialCategory()));
            procurementPlan.setDemandDept(Long.parseLong(procurementPlanUpdateVo.getDemandDept()));
            procurementPlan.setRemark(procurementPlanUpdateVo.getRemark());
            procurementPlan.setEnclosureUrl(procurementPlanUpdateVo.getEnclosureUrl());

            List<PlanUpdateVo> planList = procurementPlanUpdateVo.getMaterialList();
            for (PlanUpdateVo entity : planList) {
                procurementPlan.setPlanWeight(entity.getPlanWeight());
                procurementPlan.setQualityStandard(entity.getQualityStandard());
                procurementPlan.setDemandTime(entity.getDemandTime());
                procurementPlan.setMaterialId(entity.getMaterialId());
            }
            //调用审核
            if (procurementPlan.getStatus() == 2) {
                SysAuditHistoryVo sysAuditHistoryVo = new SysAuditHistoryVo();
                String perms = "order:purchase:plan:review";
                String auditDoc = procurementPlan.getPurchaseNum();
                sysAuditHistoryVo.setAuditDoc(auditDoc);
                sysAuditHistoryVo.setPerms(perms);
                AjaxResult history = feignService.editHistory(sysAuditHistoryVo);
                String data = JSON.parseObject(JSON.toJSONString(history.get("msg")), String.class);
                if ("操作成功".equals(data)) {
                    procurementPlan.setStatus(5);

                    //修改审核代办状态为已处理
                    feignService.updateStatus(3,procurementPlan.getPurchaseNum(),"采购计划");//

                    return updateById(procurementPlan);

                } else {
                    return false;
                }
            }
            return updateById(procurementPlan);
        } else {
            throw new GlobalException("不属于待提交和未通过的采购计划");
        }
    }

    /**
     * 提交审核
     *
     * @param id
     * @return
     */
    @Override
    public boolean submitReview(Long id) {
        ProcurementPlan procurementPlan = getById(id);
        if (5 == procurementPlan.getStatus()) {
            procurementPlan.setStatus(6);

            SysWorkbenchAuditAgentVo sysWorkbenchAuditAgentVo = new SysWorkbenchAuditAgentVo();
            sysWorkbenchAuditAgentVo.setDocConfig("order:purchase:plan:review");
            sysWorkbenchAuditAgentVo.setReceiptName("采购计划");
            sysWorkbenchAuditAgentVo.setReceiptNumber(procurementPlan.getPurchaseNum());//采购计划单号
            sysWorkbenchAuditAgentVo.setStatus(1);//待审核
            sysWorkbenchAuditAgentVo.setReceiptContent("有单据待审核,请及时审核");

            feignService.insertAuditAgent(sysWorkbenchAuditAgentVo);

            return updateById(procurementPlan);
        } else {
            throw new GlobalException("只能提交待审核得单据");
        }

    }

    /**
     * 撤销审核
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteReview(Long id) {
        ProcurementPlan procurementPlan = getById(id);
        if (6 == procurementPlan.getStatus()) {
            procurementPlan.setStatus(5);

            //删除审核代办
            feignService.deleteDoc(procurementPlan.getPurchaseNum(),"采购计划");

            return updateById(procurementPlan);
        } else {
            throw new GlobalException("只能撤销待审核的采购计划");
        }
    }

    /**
     * 删除采购计划
     *
     * @param ids
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteProcurementPlan(String ids) {
        List<String> idList = Arrays.asList(ids.split(","));
        List<ProcurementPlan> procurementPlan = procurementPlanMapper.selectList(new QueryWrapper<ProcurementPlan>().lambda().in(ProcurementPlan::getId, idList));
        List<ProcurementPlan> procurementPlanList = new ArrayList<>();
        for (ProcurementPlan entity : procurementPlan) {
            if (5 == entity.getStatus() || 2 == entity.getStatus()) {
                procurementPlanList.add(entity);

                feignService.deleteDoc(entity.getPurchaseNum(),"采购计划");

            } else {
                throw new GlobalException("只能删除待提交或者未通过的采购计划");
            }
        }
        return removeByIds(procurementPlanList);
    }

    /**
     * 撤回采购计划
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean backPlan(Long id) throws SQLException {
        ProcurementPlanDetail procurementPlanDetail = procurementPlanDetailService.getById(id);
        if (1 == procurementPlanDetail.getStatus()) {
            try {
                //获取撤回信息数据
                List<ProcurementPlanBack> procurementPlanBacks = procurementPlanBackMapper.selectList(new QueryWrapper<ProcurementPlanBack>().lambda().eq(ProcurementPlanBack::getDetailId, id));
                for (ProcurementPlanBack entity : procurementPlanBacks) {
                    //将之前下达的重量返还
                    ProcurementPlan procurementPlan = getById(entity.getPlanId());
                    BigDecimal add = new BigDecimal(procurementPlan.getSurplusNum()).add(new BigDecimal(entity.getLowerWeight()));
                    procurementPlan.setSurplusNum(add.toString());
                    if (add.toString().equals(procurementPlan.getPlanWeight())) {
                        procurementPlan.setStatus(1);
                    } else if (Integer.parseInt(add.toString()) < Integer.parseInt(procurementPlan.getPlanWeight())) {
                        procurementPlan.setStatus(8);
                    }
                    updateById(procurementPlan);
                }
                //删除明细数据，同时删除对应的撤回信息数据
                procurementPlanBackService.removeBatchByIds(procurementPlanBacks);
                return procurementPlanDetailService.removeById(procurementPlanDetail);
            } catch (Exception e) {
                throw new SQLException("批量删除失败");
            }
        } else {
            throw new GlobalException("只能撤回预下单得数据");
        }

    }

    /**
     * 关结采购计划
     *
     * @param procurementPlanVo
     * @return
     */
    @Override
    public boolean closePlan(ProcurementPlanVo procurementPlanVo) {
        ProcurementPlan procurementPlan = getById(procurementPlanVo.getId());
        procurementPlan.setStatus(4);
        procurementPlan.setCloseReason(procurementPlanVo.getCloseReason());
        return updateById(procurementPlan);
    }

    /**
     * 查看
     *
     * @param id
     * @return
     */
    @Override
    public ProcurementPlanDto getPlanById(Long id) {
        ProcurementPlanDto viewById = procurementPlanMapper.getViewById(id);
        ProcurementPlanDto procurementPlanDto = new ProcurementPlanDto();
        //获取采购计划状态缓存字典数据
        List<SysDictData> statusArray = DictUtils.getDictCache("procurement_plan_status");
        Map<String, String> actualMap = statusArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取采购计划质量标准字典数据
        List<SysDictData> standardArray = DictUtils.getDictCache("quality_standard");
        Map<String, String> qualityMap = standardArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //物料类别字典值
        List<SysDictData> categoryArray = DictUtils.getDictCache("material_category");
        Map<String, String> categoryMap = categoryArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //单位
        List<SysDictData> materialUnitArray = DictUtils.getDictCache("sys_material_unit");
        Map<String, String> materialUnit = materialUnitArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        procurementPlanDto.setStatusDict(actualMap.get(String.valueOf(viewById.getStatus())));
        procurementPlanDto.setStatus(String.valueOf(viewById.getStatus()));
        List<MaterialVo> materialVos = new ArrayList<>();
        MaterialVo materialVo = new MaterialVo();

        materialVo.setMaterialName(viewById.getMaterialName());
        materialVo.setMaterialCode(viewById.getMaterialCode());
        materialVo.setMaterialSpec(viewById.getMaterialSpec());
        materialVo.setPlannedUnitPrice(viewById.getPlannedUnitPrice());
        materialVo.setPlanWeight(viewById.getPlanWeight());
        materialVo.setMaterialId(viewById.getMaterialId());
        materialVo.setDemandTime(viewById.getDemandTime());
        materialVo.setUnit(String.valueOf(viewById.getUnit()));
        materialVo.setUnitDict(materialUnit.get(String.valueOf(viewById.getUnit())));
        materialVo.setQualityStandard(viewById.getQualityStandard());
        materialVo.setQualityStandardDict(qualityMap.get(viewById.getQualityStandard()));
        //下达重量
        ProcurementPlanBack procurementPlanBacks = procurementPlanBackMapper.selectOne(new QueryWrapper<ProcurementPlanBack>().lambda().eq(ProcurementPlanBack::getPlanId, id));
        if (procurementPlanBacks != null) {
            materialVo.setLowerWeight(procurementPlanBacks.getLowerWeight());
//            List<Long> planIds = new ArrayList<>();
//            for (ProcurementPlanBack backEntity : procurementPlanBacks) {
//                planIds.add(backEntity.getPlanId());
//            }
//            ProcurementPlanDetail procurementPlanDetails = procurementPlanDetailMapper.selectOne(new QueryWrapper<ProcurementPlanDetail>().lambda().in(ProcurementPlanDetail::getId, procurementPlanBacks.getPlanId()));
//            BigDecimal bigDecimal = new BigDecimal(0);
//            for (ProcurementPlanDetail detailEntity : procurementPlanDetails) {
//                bigDecimal = bigDecimal.add(new BigDecimal(detailEntity.getLowerWeight()));
//            }
//            if (procurementPlanDetails != null) {
//                String lowerWeight = procurementPlanDetails.getLowerWeight();
//                materialVo.setLowerWeight(lowerWeight);
//            }
        }
        materialVos.add(materialVo);
        procurementPlanDto.setMaterialList(materialVos);
        procurementPlanDto.setPurchaseNum(viewById.getPurchaseNum());
        procurementPlanDto.setMaterialCategory(String.valueOf(viewById.getMaterialCategory()));
        procurementPlanDto.setMaterialCategoryDict(categoryMap.get(String.valueOf(viewById.getMaterialCategory())));
        //部门
        AjaxResult deptInfo = feignService.getDeptInfo(Long.parseLong(viewById.getDemandDept()));
        SysDept accDetailed = JSON.parseObject(JSON.toJSONString(deptInfo.get("data")), SysDept.class);
        procurementPlanDto.setDemandDeptDict(accDetailed.getDeptName());
        procurementPlanDto.setDemandDept(String.valueOf(viewById.getDemandDept()));
        procurementPlanDto.setRemark(viewById.getRemark());
        procurementPlanDto.setEnclosureUrl(viewById.getEnclosureUrl());
        procurementPlanDto.setCloseReason(viewById.getCloseReason());
        procurementPlanDto.setId(viewById.getId());
        return procurementPlanDto;
    }

    /**
     * 审核单据
     *
     * @param orderReviewVo
     * @return
     */
    @Override
    public boolean purchaseReview(OrderReviewVo orderReviewVo) {
        ProcurementPlan procurementPlan = getById(orderReviewVo.getId());
        if (procurementPlan.getStatus() == 6 || procurementPlan.getStatus() == 7) {
            String perms = "order:purchase:plan:review";
            int isAdopt = orderReviewVo.getIsAdopt();
            String auditDoc = procurementPlan.getPurchaseNum();
            String auditRemarks = orderReviewVo.getReviewComments();
            Long userId = SecurityUtils.getUserId();
            AjaxResult sequence = feignService.getSequenceTwo(perms, 2, isAdopt, auditRemarks, auditDoc, userId);
            Integer data = JSON.parseObject(JSON.toJSONString(sequence.get("data")), Integer.class);
            if (data == null) {
                throw new GlobalException("未对该审核进行配置");
            }
            //1:通过，2：审核中，3：没权限 4:该人已经审核过
            if (orderReviewVo.getIsAdopt() == 1) {
                if (data == 1) {
                    procurementPlan.setStatus(1);
                    if (procurementPlan.getReviewBy() == null) {
                        procurementPlan.setReviewBy(SecurityUtils.getUsername());
                    } else {
                        procurementPlan.setReviewBy(procurementPlan.getReviewBy() + "," + SecurityUtils.getUsername());
                    }
                    procurementPlan.setReviewTime(new Date());

                    feignService.updateStatus(3,procurementPlan.getPurchaseNum(),"采购计划");

                    return updateById(procurementPlan);
                } else if (data == 2) {
                    procurementPlan.setStatus(7);
                    if (procurementPlan.getReviewBy() == null) {
                        procurementPlan.setReviewBy(SecurityUtils.getUsername());
                    } else {
                        procurementPlan.setReviewBy(procurementPlan.getReviewBy() + "," + SecurityUtils.getUsername());
                    }
                    procurementPlan.setReviewTime(new Date());
                    return updateById(procurementPlan);
                } else if (data == 3) {
                    throw new GlobalException("没有审核权限");
                } else {
                    throw new GlobalException("该用户已经审核过");
                }
            } else {
                if (data == 1 || data == 2) {
                    procurementPlan.setStatus(2);
                    if (procurementPlan.getReviewBy() == null) {
                        procurementPlan.setReviewBy(SecurityUtils.getUsername());
                    } else {
                        procurementPlan.setReviewBy(procurementPlan.getReviewBy() + "," + SecurityUtils.getUsername());
                    }

                    SysWorkbenchAuditAgentVo sysWorkbenchAuditAgentVo = new SysWorkbenchAuditAgentVo();
                    sysWorkbenchAuditAgentVo.setDocConfig("order:purchase:plan:review");
                    sysWorkbenchAuditAgentVo.setReceiptName("采购计划");
                    sysWorkbenchAuditAgentVo.setReceiptNumber(procurementPlan.getPurchaseNum());//采购需求单号
                    sysWorkbenchAuditAgentVo.setStatus(2);//待处理

                    sysWorkbenchAuditAgentVo.setPassFlag("1");
                    sysWorkbenchAuditAgentVo.setCreateName(procurementPlan.getCreateBy());

                    sysWorkbenchAuditAgentVo.setReceiptContent("有单据未通过,请及时查看");

                    feignService.insertAuditAgent(sysWorkbenchAuditAgentVo);

                    procurementPlan.setReviewTime(new Date());
                    return updateById(procurementPlan);
                } else if (data == 3) {
                    throw new GlobalException("没有审核权限");
                } else {
                    throw new GlobalException("该用户已经审核过");
                }
            }
        } else {
            throw new GlobalException("状态为“待合同审核”和“合同审核中”的单据才能进行审核");
        }
    }
}
